// 游戏控制器
(function (w) {
    // 声明一个变量，用来保存this的指向
    let that = null
    // 1. 声明一个创建游戏控制器的构造函数
    function Game(map) {
        // 游戏控制器里应该有食物对象，食物是调用创建食物的构造函数创建
        this.food = new Food()
        // 游戏控制器里应该有蛇对象，蛇是调用创建蛇的构造函数创建
        this.snake = new Snake()
        // 游戏控制器里要有游戏地图的数据，由外部参数传递进来的
        this.map = map

        // 把游戏控制器里的this赋值给that
        that = this
    }
    // 2. 游戏开始的方法
    Game.prototype.start = function () {
        // 2.1 渲染食物对象和蛇对象
        this.food.render(this.map)
        this.snake.render(this.map)
        // 2.2 调用蛇移动的方法让蛇移动并重新渲染页面
        snakeMove()

        // 调用方向控制方法
        bindKey()
    }
    // 3. 写一个方法，让蛇不停地动起来
    function snakeMove() {
        let timerID = setInterval(function () {
            this.snake.move(this.food, this.map)
            // 判断蛇头的位置是否出界
            // 如果蛇头的坐标小于0或者大于等于地图的宽/高，就代表出界了
            let snakeHeadX = this.snake.body[0].x * this.snake.width
            let snakeHeadY = this.snake.body[0].y * this.snake.height
            if (snakeHeadX < 0 || snakeHeadY < 0 || snakeHeadY >= this.map.offsetHeight || snakeHeadX >= this.map.offsetWidth) {
                alert(`GAME  OVER!!!\n出界了，游戏结束`)
                clearInterval(timerID)
                return // 如果蛇头移动后的坐标是出界的坐标，就停止其后代码的执行
            }
            this.snake.render(this.map)
            // 因为这里的this指向的是window，所以我们通过 .bind() 方法来修改this的指向
            // 将that写进 .bind() 方法中，that代表的是游戏控制器的this
        }.bind(that), 200)
    }
    // 4. 写一个方法，让蛇跟着键盘按键移动
    function bindKey() {
        // 给页面设置键盘按下事件,获取按键，修改蛇的移动方向
        document.onkeydown = function (e) {
            e = e || window.event
            // console.log(e.keyCode);
            // 左37  上38  右39  下40   A65  W87  D68  S83
            switch (e.keyCode) {
                case 37:
                case 65:
                    if (this.snake.direction != 'right') {
                        this.snake.direction = 'left'
                    }
                    break;
                case 38:
                case 87:
                    if (this.snake.direction != 'bottom') {
                        this.snake.direction = 'top'
                    }
                    break;
                case 39:
                case 68:
                    if (this.snake.direction != 'left') {
                        this.snake.direction = 'right'
                    }
                    break;
                case 40:
                case 83:
                    if (this.snake.direction != 'top') {
                        this.snake.direction = 'bottom'
                    }
                    break;
            }
        }.bind(that)
    }
    // 把Game暴露出去
    w.Game = Game
}(window))